--- /dev/null
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place - Suite 330, Boston, MA 02111 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+\f
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+\f
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+\f
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+\f
+ Appendix: How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
--- /dev/null
+CFLAGS=-g
+
+FMTS=magproto.o gpx.o geo.o gpsman.o mapsend.o mapsource.o \
+ gpsutil.o tiger.o pcx.o csv.o
+
+OBJS=main.o queue.o route.o waypt.o util.o vecs.o $(FMTS)
+
+gpsbabel: $(OBJS)
+ $(CC) $(CFLAGS) $(OBJS) -o gpsbabel -lexpat -lm
+
+clean:
+ rm -f $(OBJS) gpsbabel
+
+mapsend.o: mapsend.h
+magproto.o: magellan.h
--- /dev/null
+
+THE PROBLEM
+
+ There are simply too many gratituosuly different file formats to
+ hold waypoint and route information in various programs used by
+ computers. GPX (http://www.topografix.com/gpx.asp) attempts to
+ define a standard in XML to contain all the data, but there are
+ too many programs that don't understand it yet and too much data
+ that are in an alternate format.
+
+THE SOLUTION
+
+ I needed to convert waypoints between a couple of formats, so
+ I whipped up a converter and based it on an extensible foundation
+ so that it was easy to add new formats. Most file formats added
+ so far have taken under 200 lines of reasonable ISO C so they can
+ be stamped out pretty trivially.
+
+THE FORMATS
+
+ GPX
+
+ This is the most capable and expressive of all the file formats
+ supplied. It is described at http://www.topografix.com/gpx.asp
+ and is supported by EasyGPS, ExpertGPS, and man other programs
+ described at http://www.topografix.com/gpx_resources.asp
+
+ GEO
+
+ geocaching.com spits up geocaching.loc files that are XML-ish but
+ not quite GPX. Becuase it's so close to GPX, this format is very
+ well supported.
+
+ MAGELLAN
+
+ Waypoint upload and download works reliably.
+
+ As of this writing, there is still a lot of "scribbling" in the
+ source for functionality that isn't hooked up to the rest of the
+ program. Communication errors are handled and verification of
+ data is turned on.
+
+ GPSMAN
+
+ GPS Manager can read and write formats that this converter doesn't
+ understand. The default formats (WGS84, DDD) work reliably.
+
+ GPSUTIL
+
+ GPSUtil has a simple file format of this program that runs on POSIX-
+ compliant OSes like UNIX and Linux. Reads and writes of this format
+ are reliable. (I've also contributed to this program.) It's
+ available at http://www.cs.uakron.edu/~hennings/gpsutil/.
+
+ TIGER
+
+ The U.S. Census Bureau proives online mapping facilities. This
+ format is described at: http://tiger.census.gov/instruct.html.
+
+ CSV
+
+ There are a billion variants of Comma Separated Value data. This
+ is the one that makes Delorme S&A Deluxe 9 happy.
+
+ MAPSEND
+
+ Magellan was smart enough to document their file format to make
+ creating software like this possible. It reads and writes only
+ waypoints (not routes) at this time.
+
+ PCX
+
+ Garmin documents only PCX5, an older format limited to the lame NMEA
+ six-character waypoint names that's treated as a second-class citizien
+ in current versions of MapSource. Use file->import to read these
+ files. Anyone with information on the *.mps file format that is
+ now preferred is encouraged to contact me with the details or better
+ yet, a module that implements it. I spent time trying to reverse-
+ engineer a couple of *.mps files then I remembered that I don't own
+ a Garmin and wasn't that inspired.
+
+
+COMMON USAGE
+
+ Invocation was meant to be flexible. Unfortunately, that can
+ sometimes lead to unwieldy command lines.
+
+ mgps -?
+
+ will always show you the supported file types. To use this
+ program, just tell it what you're reading, where to read it from,
+ what you're writing, and what to write it to. For example:
+
+ mgps -i geo -f /tmp/geocaching.loc -o gpx -F /tmp/geocaching.gpx
+
+ tells it to read the first file in geocaching.com format and create
+ a new file in GPX format.
+
+
+ADVANCED USAGE
+
+ Argument are processed in the order they appear on the command line.
+ Input is cumulative. The input file type remains unchanged until a
+ new -i argument is seen. Files are read in the order they appear.
+ So you could merge three input files into one output file with:
+
+ mgps -i geo 1.loc 2.loc 3.loc -o geo -F big.loc
+
+ You can merge files of different types:
+
+ mgps -i geo 1.loc -i gpx 2.gpx -i pcx 3.pcx -o gpsutil -F big.gps
+
+ You can write the same data in different output formats:
+
+ mgps -i geo 1.loc -o gpx -F 1.gpx -o pcx 1.wpt
--- /dev/null
+If you're interested in contributing to this program, here are some
+guidelines. Mail patches to robertlipe@usa.net for consideration and
+integration.
+
+Standards are good. ISO C and POSIX are greal preferred.
+
+Reuse is OK, if not onerous. For example, using the expat libraries vastly
+ simplifies the XML parsers while increasing their robustness plus those
+ libraries are ubiquitous. So I consider it OK to require expat.
+
+If you contribute a new target, contribute a test case along with it. It's
+not that hard and it helps us be sure that the next version of thie program
+doesn't break your file format.
+
+Compilers complain for a reason. Code shouldn't emit warnings.
+
+The entire world doesn't run <your OS here>. I've tested this code on
+five different OSes. If you find yourself wanting to insert compiler or
+OS specific magic, please resist.
+
+Enjoy!
+
+Robert Lipe,
+robertlipe@usa.net
--- /dev/null
+/*
+ Comma separated value files.
+ NAME,LONG, LAT.
+
+ Copyright (C) 2002 Robert Lipe, robertlipe@usa.net
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
+
+ */
+
+#include "defs.h"
+#include <ctype.h>
+
+static FILE *file_in;
+static FILE *file_out;
+
+static void
+rd_init(const char *fname)
+{
+ file_in = fopen(fname, "r");
+ if (file_in == NULL) {
+ fatal("GPSUTIL: Cannot open %s for reading\n", fname);
+ }
+}
+
+static void
+rd_deinit(void)
+{
+ fclose(file_in);
+}
+
+static void
+wr_init(const char *fname)
+{
+ file_out = fopen(fname, "w");
+ if (file_out == NULL) {
+ fatal("GPSUTIL: Cannot open %s for writing\n", fname);
+ }
+}
+
+static void
+wr_deinit(void)
+{
+ fclose(file_out);
+}
+
+static void
+data_read(void)
+{
+ char name[9], desc[80];
+ char *odesc = desc;
+ double lat,lon;
+ char latdir, londir;
+ long alt;
+ char alttype;
+ char icon[3] = {0};
+ waypoint *wpt_tmp;
+
+ while( fscanf(file_in, "%lf,%lf,%80[^\n]",
+ &lat, &lon, desc) > 0) {
+ wpt_tmp = calloc(sizeof(*wpt_tmp),1);
+ if (wpt_tmp == NULL) {
+ fatal("GPSMAN: cannot allocate memory\n");
+ }
+ while (*odesc == ' ' || *odesc == '\t') {
+ odesc++;
+ }
+ wpt_tmp->shortname = strdup(odesc);
+ wpt_tmp->creation_time = time(NULL);
+
+ wpt_tmp->position.longitude.degrees = lon;
+ wpt_tmp->position.latitude.degrees = lat;
+
+ waypt_add(wpt_tmp);
+ }
+}
+
+static void
+gpsutil_disp(waypoint *wpt)
+{
+ double lon,lat;
+ signed int ilon, ilat;
+ const char *icon_token = "0";
+ char tbuf[1024];
+ char *tp = tbuf;
+ time_t tm = wpt->creation_time;
+
+ lon = wpt->position.longitude.degrees;
+ lat = wpt->position.latitude.degrees;
+
+ fprintf(file_out, "%08.5f, %08.5f, %s\n",
+ lat,
+ lon,
+ wpt->description);
+
+}
+
+static void
+data_write(void)
+{
+ waypt_disp_all(gpsutil_disp);
+}
+
+
+ff_vecs_t csv_vecs = {
+ rd_init,
+ wr_init,
+ rd_deinit,
+ wr_deinit,
+ data_read,
+ data_write,
+};
--- /dev/null
+/*
+ Copyright (C) 2002 Robert Lipe, robertlipe@usa.net
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
+
+ */
+
+#include <time.h>
+#include <stdlib.h>
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include "queue.h"
+
+/*
+ * Common definitions. There should be no protocol or file-specific
+ * data in this file.
+ */
+
+/*
+ * A coordinate in space.
+ */
+typedef struct {
+ double degrees;
+} coord;
+
+
+/*
+ * An altitude is essentially a coordinate along only the Z axis.
+ */
+
+typedef struct {
+ double altitude_meters;
+} altitude;
+
+
+/*
+ * A triplet of the coordinates along the three axes describes
+ * a position.
+ */
+typedef struct {
+ coord latitude;
+ coord longitude;
+ altitude altitude;
+} position;
+
+
+/*
+ * This is a waypoint, as stored in the GPSR. It tries to not
+ * cater to any specific model or protocol. Anything that needs to
+ * be truncated, edited, or otherwise trimmed should be done on the
+ * way to the target.
+ */
+typedef struct {
+ queue Q;
+ position position;
+ time_t time_created;
+ char *shortname;
+ char *description;
+ char *url;
+ char *url_link_text;
+ const char *icon_descr;
+ time_t creation_time;
+} waypoint;
+
+typedef void (*ff_init) (char const *);
+typedef void (*ff_deinit) (void);
+typedef void (*ff_read) (void);
+typedef void (*ff_write) (void);
+
+typedef void (*waypt_cb) (waypoint *);
+void waypt_add (waypoint *);
+void route_add (waypoint *);
+void waypt_disp_all(waypt_cb);
+unsigned int waypt_count(void);
+void fprintdms(FILE *, coord *, int);
+
+typedef struct ff_vecs {
+ ff_init rd_init;
+ ff_init wr_init;
+ ff_deinit rd_deinit;
+ ff_deinit wr_deinit;
+ ff_read read;
+ ff_write write;
+} ff_vecs_t;
+
+void waypt_init(void);
+void route_init(void);
+void waypt_disp(waypoint *);
+void fatal(const char *, ...);
+ff_vecs_t *find_vec(char *);
+
+void printposn(coord *c, int is_lat);
--- /dev/null
+/*
+ Copyright (C) 2002 Robert Lipe, robertlipe@usa.net
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
+
+ */
+
+#include <expat.h>
+#include "defs.h"
+
+static int in_wpt;
+static int in_name;
+static int in_link;
+
+static XML_Parser psr;
+static waypoint *wpt_tmp;
+
+FILE *fd;
+FILE *ofd;
+
+static void
+tag_coord(const char **attrv)
+{
+ const char **avp = &attrv[0];
+
+
+ while (*avp) {
+ if (strcmp(avp[0], "lat") == 0) {
+ sscanf(avp[1], "%lf",
+ &wpt_tmp->position.latitude.degrees);
+ }
+ else if (strcmp(avp[0], "lon") == 0) {
+ sscanf(avp[1], "%lf",
+ &wpt_tmp->position.longitude.degrees);
+ }
+ avp+=2;
+ }
+}
+
+static void
+tag_name(const char **attrv)
+{
+ const char **avp = &attrv[0];
+ while (*avp) {
+ if (strcmp(avp[0], "id") == 0) {
+ wpt_tmp->shortname = strdup(avp[1]);
+ }
+ avp+=2;
+ }
+}
+
+static void
+tag_link(const char **attrv)
+{
+ const char **avp = &attrv[0];
+ while (*avp) {
+ if (strcmp(avp[0], "text") == 0) {
+ wpt_tmp->url_link_text = strdup(avp[1]);
+ }
+ avp+=2;
+ }
+}
+
+static void
+geo_start(void *data, const char *el, const char **attr)
+{
+
+ if (in_wpt) {
+ if (strcmp(el, "ele") == 0) {
+ wpt_tmp->position.altitude.altitude_meters = atoi(attr[1]);
+ }
+ else if (strcmp(el, "name") == 0) {
+ tag_name(attr);
+ }
+ else if (strcmp(el, "coord") == 0) {
+ tag_coord(attr);
+ }
+ }
+
+ if (strcmp(el, "waypoint") == 0) {
+ wpt_tmp = calloc(sizeof(*wpt_tmp), 1);
+ in_wpt++;
+ } else if (strcmp(el, "name") == 0) {
+ in_name++;
+ } else if (strcmp(el, "link") == 0) {
+ tag_link(attr);
+ in_link++;
+ }
+}
+
+static void
+geo_end(void *data, const char *el)
+{
+ if (strcmp(el, "waypoint") == 0) {
+ waypt_add(wpt_tmp);
+ in_wpt--;
+ }
+ else if (strcmp(el, "name") == 0) {
+ in_name--;
+ }
+ else if (strcmp(el, "link") == 0) {
+ in_link--;
+ }
+}
+
+static void
+geo_cdata(void *dta, const XML_Char *s, int len)
+{
+ char *foo = malloc(len+1);
+ foo[len] = 0;
+ strncpy(foo, s, len);
+ if (in_name) {
+ wpt_tmp->description = foo;
+ }
+ if (in_link) {
+ wpt_tmp->url = foo;
+ }
+}
+
+
+void
+geo_rd_init(const char *fname)
+{
+ fd = fopen(fname, "r");
+ if (fd == NULL) {
+ abort();
+ }
+
+ psr = XML_ParserCreate(NULL);
+ if (!psr) {
+ abort();
+ }
+
+ XML_SetElementHandler(psr, geo_start, geo_end);
+ XML_SetCharacterDataHandler(psr, geo_cdata);
+}
+
+void
+geo_rd_deinit(void)
+{
+ fclose(fd);
+}
+
+void
+geo_wr_init(const char *fname)
+{
+ ofd = fopen(fname, "w");
+ if (ofd == NULL) {
+ abort();
+ }
+}
+
+void
+geo_wr_deinit(void)
+{
+ fclose(ofd);
+}
+
+void
+geo_read(void)
+{
+ int len;
+ char buf[1024];
+
+ while ((len = fread(buf, 1, sizeof(buf), fd))) {
+ if (!XML_Parse(psr, buf, len, feof(fd))) {
+ fprintf(stderr, "Parse error at %d: %s\n",
+ XML_GetCurrentLineNumber(psr),
+ XML_ErrorString(XML_GetErrorCode(psr)));
+ exit(1);
+ }
+ }
+
+}
+
+static void
+geo_waypt_pr(waypoint *waypointp)
+{
+ fprintf(ofd, "<waypoint>\n");
+ fprintf(ofd, "<name id=\"%s\">", waypointp->shortname);
+ fprintf(ofd, "<![CDATA[%s]]>", waypointp->description);
+ fprintf(ofd, "</name>\n");
+
+ fprintf(ofd, "<coord lat=\"%lf\" lon=\"%lf\">",
+ waypointp->position.latitude.degrees,
+ waypointp->position.longitude.degrees);
+ fprintf(ofd, "</coord>\n");
+
+ fprintf(ofd, "<link text =\"Cache Details\">%s</link>\n",
+ waypointp->url);
+ fprintf(ofd, "</waypoint>\n");
+}
+
+void
+geo_write(void)
+{
+ fprintf(ofd, "<?xml version=\"1.0\"?><loc version=\"1.0\" src=\"EasyGPS\">\n");
+ waypt_disp_all(geo_waypt_pr);
+ fprintf(ofd, "</loc>\n");
+}
+
+ff_vecs_t geo_vecs = {
+ geo_rd_init,
+ geo_wr_init,
+ geo_rd_deinit,
+ geo_wr_deinit,
+ geo_read,
+ geo_write,
+};
--- /dev/null
+<?xml version="1.0"?><loc version="1.0" src="EasyGPS"><waypoint><name id="GCEBB"><![CDATA[Mountain Bike Heaven by susy1313]]></name><coord lat="35.9720333333333" lon="-87.1347"/><type>geocache</type><link text="Cache Details">http://www.geocaching.com/seek/cache_details.asp?ID=3771</link></waypoint><waypoint><name id="GC1A37"><![CDATA[The Troll by a182pilot & Family]]></name><coord lat="36.0906833333333" lon="-86.67955"/><type>geocache</type><link text="Cache Details">http://www.geocaching.com/seek/cache_details.asp?ID=6711</link></waypoint><waypoint><name id="GC1C2B"><![CDATA[Dive Bomber by JoGPS & family]]></name><coord lat="35.9962666666667" lon="-86.6201166666667"/><type>geocache</type><link text="Cache Details">http://www.geocaching.com/seek/cache_details.asp?ID=7211</link></waypoint><waypoint><name id="GC25A9"><![CDATA[FOSTER by JoGPS & Family]]></name><coord lat="36.0384833333333" lon="-86.6486166666667"/><type>geocache</type><link text="Cache Details">http://www.geocaching.com/seek/cache_details.asp?ID=9641</link></waypoint><waypoint><name id="GC2723"><![CDATA[Logan Lighthouse by JoGps & Family]]></name><coord lat="36.1121833333333" lon="-86.7417666666667"/><type>geocache</type><link text="Cache Details">http://www.geocaching.com/seek/cache_details.asp?ID=10019</link></waypoint><waypoint><name id="GC2B71"><![CDATA[Ganier Cache by Susy1313]]></name><coord lat="36.0640833333333" lon="-86.7905166666667"/><type>geocache</type><link text="Cache Details">http://www.geocaching.com/seek/cache_details.asp?ID=11121</link></waypoint><waypoint><name id="GC309F"><![CDATA[Shy's Hill by FireFighterEng33]]></name><coord lat="36.0877666666667" lon="-86.8097333333333"/><type>geocache</type><link text="Cache Details">http://www.geocaching.com/seek/cache_details.asp?ID=12447</link></waypoint><waypoint><name id="GC317A"><![CDATA[GittyUp by JoGPS / Warner Parks]]></name><coord lat="36.0575" lon="-86.892"/><type>geocache</type><link text="Cache Details">http://www.geocaching.com/seek/cache_details.asp?ID=12666</link></waypoint><waypoint><name id="GC317D"><![CDATA[Inlighting by JoGPS / Warner Parks]]></name><coord lat="36.0828" lon="-86.8672833333333"/><type>geocache</type><link text="Cache Details">http://www.geocaching.com/seek/cache_details.asp?ID=12669</link></waypoint></loc>
\ No newline at end of file
--- /dev/null
+% Written by GPSManager 05-Apr-2002 21:52:36 (EST)
+% Edit at your own risk!
+
+!Format: DMS 1 WGS 84
+!Creation: no
+
+!W:
+GC894 N41 20 07.9 W85 24 31.9 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+GC1F78 N40 43 04.1 W85 06 25.1 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+003 N41 07 21.3 W85 09 23.5 symbol=boat_ramp alt=220.506469727 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+GC93 N41 43 09.4 W85 58 59.9 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+GC2193 N40 25 29.0 W86 54 52.0 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+004 N41 07 22.6 W85 09 24.3 symbol=flag alt=250.787719727 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+GCA80 N40 29 14.3 W86 51 50.5 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+GC28CB N40 50 32.8 W85 25 20.8 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+GC2665 N40 45 56.4 W85 35 58.3 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+005 N41 02 51.4 W85 16 41.6 symbol=flag alt=263.044433594 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+GCB78 N40 26 17.9 W86 54 02.2 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+GC2ADC N40 26 16.4 W86 48 21.6 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+ABACUS N41 04 20.6 W85 13 50.8 symbol=building alt=243.577880859 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+GCD85 N41 05 03.3 W85 08 11.1 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+GCB8 N40 26 09.5 W87 09 49.1 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+GC2BE8 N40 52 45.9 W85 32 26.1 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+CASH1 N41 04 41.8 W85 08 19.3 symbol=flag alt=245.740844727 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+H0ME N41 02 51.7 W85 16 42.1 symbol=house alt=272.176879883 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+GC2C81 N41 12 24.2 W85 02 23.5 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+CENCEN N41 41 39.0 W86 14 53.3 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+TOSB2 N41 44 00.4 W84 59 46.4 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+GC2C90 N40 50 08.2 W85 27 14.9 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+CWORK N41 07 23.0 W85 09 24.7 symbol=flag alt=254.633056641 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+TOSB3 N41 43 21.9 W86 15 20.3 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+GC2C91 N41 05 01.4 W85 08 18.7 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+FRSB1 N41 40 34.1 W86 15 01.1 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+UNITA N41 02 52.2 W85 16 41.6 symbol=flag alt=256.795898438 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+GC2F53 N41 43 57.0 W86 04 48.3 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+FRSB2 N41 38 10.3 W86 15 04.4 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+GC333A N41 01 42.7 W85 11 49.3 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+FRSB4 N41 37 27.7 W86 15 08.7 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+FRSB5 N41 38 53.4 W85 56 55.0 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+GC34D4 N41 58 16.8 W86 11 05.3 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+FRSB6 N41 34 46.3 W85 50 01.8 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+GC42A1 N41 05 02.1 W85 03 14.2 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+GC37C4 N41 38 15.5 W85 54 19.6 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+FRSB7 N41 07 42.2 W85 11 47.8 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+GC4378 N40 53 27.2 W85 28 13.4 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+GC11EF N40 01 45.3 W86 53 17.4 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+GC44E5 N41 01 03.7 W85 15 07.0 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+GC12FF N41 33 23.9 W86 21 26.9 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+GC47A5 N40 25 15.3 W86 54 17.6 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+GC17E0 N41 52 01.5 W86 36 12.5 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+GC488D N41 33 43.7 W85 50 18.3 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+GC1A9C N41 06 36.2 W85 09 20.8 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+
--- /dev/null
+/*
+ Copyright (C) 2002 Robert Lipe, robertlipe@usa.net
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
+
+ */
+
+#include "defs.h"
+
+static FILE *in_file;
+static FILE *out_file;
+
+static void
+gpsman_rd_init(const char *fname)
+{
+ in_file = fopen(fname, "r");
+ if (in_file == NULL) {
+ fatal("GPSMAN: Cannot open %s for reading\n", fname);
+ }
+
+}
+static void
+gpsman_rd_deinit(void)
+{
+ fclose(in_file);
+}
+
+static void
+gpsman_wr_init(const char *fname)
+{
+ out_file = fopen(fname, "w");
+ if (out_file == NULL) {
+ fatal("GPSMAN: Cannot open %s for writing\n", fname);
+ }
+
+ fprintf(out_file, "!Format: DDD 1 WGS 84\n");
+}
+
+static void
+gpsman_wr_deinit(void)
+{
+ fclose(out_file);
+}
+
+static void
+gpsman_disp(waypoint *waypointp)
+{
+ fprintf(out_file, "%-8.8s\t%s\t",
+ waypointp->shortname, waypointp->description);
+ fprintdms(out_file, &waypointp->position.latitude, 1);
+ fprintdms(out_file, &waypointp->position.longitude, 0);
+ fprintf(out_file,"\n");
+}
+
+static void
+gpsman_parse_cmd(const char *cmd)
+{
+ return;
+}
+
+static void
+gpsman_read(void)
+{
+ char latdir, londir;
+ double latf, lonf;
+ int lonm, latm;
+ double lat, lon;
+ char sname[20];
+ char descr[100];
+ char ibuf[100];
+ waypoint *wpt_tmp;
+
+ while( fgets(ibuf, sizeof(ibuf), in_file)) {
+ if (ibuf[0] == '%' || ibuf[0] == '\n' ) {
+ continue;
+ }
+ if (ibuf[0] == '!') {
+ gpsman_parse_cmd(&ibuf[1]);
+ continue;
+ }
+
+ sscanf(ibuf, "%[^\t] %[^\t] %c%d %lf %c%d %lf",
+ sname, descr, &latdir, &latm, &latf, &londir, &lonm, &lonf);
+
+ wpt_tmp = calloc(sizeof(*wpt_tmp),1);
+
+ if (wpt_tmp == NULL) {
+ fatal("GPSMAN: Cannot allocate enough memory\n");
+ }
+
+ lat = latm + latf;
+ lon = lonm + lonf;
+
+ if (latdir == 'S') lat = -lat;
+ if (londir == 'W') lon = -lon;
+
+ wpt_tmp->position.longitude.degrees = lon;
+ wpt_tmp->position.latitude.degrees = lat;
+ wpt_tmp->shortname = strdup(sname);
+ wpt_tmp->description = strdup(descr);
+
+ waypt_add(wpt_tmp);
+ }
+}
+
+static void
+gpsman_write(void)
+{
+ fprintf(out_file, "!W:\n");
+ waypt_disp_all(gpsman_disp);
+}
+
+ff_vecs_t gpsman_vecs = {
+ gpsman_rd_init,
+ gpsman_wr_init,
+ gpsman_rd_deinit,
+ gpsman_wr_deinit,
+ gpsman_read,
+ gpsman_write,
+};
--- /dev/null
+% Written by GPSManager 24-May-2002 13:51:04 (CST)
+% Edit at your own risk!
+
+!Format: DMM 1 WGS 84
+!Creation: no
+
+!W:
+!Position: DMS
+GC37C4 N41 38 15.5 W85 54 19.6 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+H0ME N41 02 51.7 W85 16 42.1 symbol=house alt=272.176879883 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+GC894 N41 20 07.9 W85 24 31.9 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+FRSB7 N41 07 42.2 W85 11 47.8 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+GC2C81 N41 12 24.2 W85 02 23.5 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+GC1F78 N40 43 04.1 W85 06 25.1 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+GC4378 N40 53 27.2 W85 28 13.4 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+TOSB2 N41 44 00.4 W84 59 46.4 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+CENCEN N41 41 39.0 W86 14 53.3 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+003 N41 07 21.3 W85 09 23.5 symbol=boat_ramp alt=220.506469727 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+GC11EF N40 01 45.3 W86 53 17.4 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+GC2C90 N40 50 08.2 W85 27 14.9 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+GC93 N41 43 09.4 W85 58 59.9 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+GC12FF N41 33 23.9 W86 21 26.9 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+GC44E5 N41 01 03.7 W85 15 07.0 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+CWORK N41 07 23.0 W85 09 24.7 symbol=flag alt=254.633056641 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+GC2193 N40 25 29.0 W86 54 52.0 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+GC47A5 N40 25 15.3 W86 54 17.6 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+TOSB3 N41 43 21.9 W86 15 20.3 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+004 N41 07 22.6 W85 09 24.3 symbol=flag alt=250.787719727 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+GC17E0 N41 52 01.5 W86 36 12.5 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+GC2C91 N41 05 01.4 W85 08 18.7 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+GCA80 N40 29 14.3 W86 51 50.5 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+GC488D N41 33 43.7 W85 50 18.3 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+FRSB1 N41 40 34.1 W86 15 01.1 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+GC28CB N40 50 32.8 W85 25 20.8 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+GC1A9C N41 06 36.2 W85 09 20.8 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+UNITA N41 02 52.2 W85 16 41.6 symbol=flag alt=256.795898438 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+GC2665 N40 45 56.4 W85 35 58.3 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+GC2F53 N41 43 57.0 W86 04 48.3 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+005 N41 02 51.4 W85 16 41.6 symbol=flag alt=263.044433594 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+GCB78 N40 26 17.9 W86 54 02.2 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+FRSB2 N41 38 10.3 W86 15 04.4 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+GC2ADC N40 26 16.4 W86 48 21.6 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+FRSB4 N41 37 27.7 W86 15 08.7 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+GC333A N41 01 42.7 W85 11 49.3 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+ABACUS N41 04 20.6 W85 13 50.8 symbol=building alt=243.577880859 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+FRSB5 N41 38 53.4 W85 56 55.0 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+GCD85 N41 05 03.3 W85 08 11.1 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+GC34D4 N41 58 16.8 W86 11 05.3 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+GCB8 N40 26 09.5 W87 09 49.1 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+FRSB6 N41 34 46.3 W85 50 01.8 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+GC2BE8 N40 52 45.9 W85 32 26.1 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+GC42A1 N41 05 02.1 W85 03 14.2 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+CASH1 N41 04 41.8 W85 08 19.3 symbol=flag alt=245.740844727 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+
+!Position: DMM
+!R: 34
+!Position: DMS
+003 N41 07 21.3 W85 09 23.5 symbol=boat_ramp alt=220.506469727 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+004 N41 07 22.6 W85 09 24.3 symbol=flag alt=250.787719727 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+005 N41 02 51.4 W85 16 41.6 symbol=flag alt=263.044433594 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+ABACUS N41 04 20.6 W85 13 50.8 symbol=building alt=243.577880859 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+CASH1 N41 04 41.8 W85 08 19.3 symbol=flag alt=245.740844727 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+CENCEN N41 41 39.0 W86 14 53.3 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+CWORK N41 07 23.0 W85 09 24.7 symbol=flag alt=254.633056641 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+FRSB1 N41 40 34.1 W86 15 01.1 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+GC11EF N40 01 45.3 W86 53 17.4 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+GCD85 N41 05 03.3 W85 08 11.1 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+
+!R: 23 Route 23
+!NB: blah blah blah
+
+GC11EF N40 01 45.3 W86 53 17.4 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+GC12FF N41 33 23.9 W86 21 26.9 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+GC1A9C N41 06 36.2 W85 09 20.8 alt=-0.114379882812 GD108:class=|c! GD108:colour=~|Z GD108:attrs=` GD108:depth=QY|c%|_i GD108:state=|cAA GD108:country=|cAA
+
--- /dev/null
+/*
+ * written by robertlipe@usa.net
+ */
+
+#include "defs.h"
+#include "magellan.h"
+
+static FILE *file_in;
+static FILE *file_out;
+
+static void
+rd_init(const char *fname)
+{
+ file_in = fopen(fname, "r");
+ if (file_in == NULL) {
+ fatal("GPSUTIL: Cannot open %s for reading\n", fname);
+ }
+}
+
+static void
+rd_deinit(void)
+{
+ fclose(file_in);
+}
+
+static void
+wr_init(const char *fname)
+{
+ file_out = fopen(fname, "w");
+ if (file_out == NULL) {
+ fatal("GPSUTIL: Cannot open %s for writing\n", fname);
+ }
+}
+
+static void
+wr_deinit(void)
+{
+ fclose(file_out);
+}
+
+static void
+data_read(void)
+{
+ char name[9], desc[30];
+ double lat,lon;
+ char latdir, londir;
+ long alt;
+ char alttype;
+ char icon[3] = {0};
+ waypoint *wpt_tmp;
+
+ while( fscanf(file_in, "%s %le%c %le%c %ld%c %30[^,] %c",
+ name, &lat, &latdir, &lon, &londir,
+ &alt, &alttype, desc, icon) > 0) {
+ wpt_tmp = calloc(sizeof(*wpt_tmp),1);
+ if (wpt_tmp == NULL) {
+ fatal("GPSMAN: cannot allocate memory\n");
+ }
+ wpt_tmp->position.altitude.altitude_meters = alt;
+ wpt_tmp->shortname = strdup(name);
+ wpt_tmp->description = strdup(desc);
+ wpt_tmp->creation_time = time(NULL);
+
+ if (latdir == 'S') lat = -lat;
+ if (londir == 'W') lon = -lon;
+ wpt_tmp->position.longitude.degrees = lon/100.0;
+ wpt_tmp->position.latitude.degrees = lat/100.0;
+ wpt_tmp->icon_descr = strdup(icon);
+
+ waypt_add(wpt_tmp);
+ }
+}
+
+static void
+gpsutil_disp(waypoint *wpt)
+{
+ double lon,lat;
+ const char *icon_token;
+
+ icon_token = mag_find_token_from_descr(wpt->icon_descr);
+
+ lon = wpt->position.longitude.degrees * 100.0;
+ lat = wpt->position.latitude.degrees * 100.0;
+
+ fprintf(file_out, "%-8s %08.3f%c %09.3f%c %07.0f%c %-30.30s %s\n",
+ wpt->shortname,
+ fabs(lat),
+ lat < 0.0 ? 'S' : 'N',
+ fabs(lon),
+ lon < 0.0 ? 'W' : 'E',
+ wpt->position.altitude.altitude_meters,
+ 'm',
+ wpt->description,
+ icon_token);
+}
+
+static void
+data_write(void)
+{
+ waypt_disp_all(gpsutil_disp);
+}
+
+
+ff_vecs_t gpsutil_vecs = {
+ rd_init,
+ wr_init,
+ rd_deinit,
+ wr_deinit,
+ data_read,
+ data_write,
+};
--- /dev/null
+/*
+ Access GPX data files.
+
+ Copyright (C) 2002 Robert Lipe, robertlipe@usa.net
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
+
+ */
+
+#include <expat.h>
+#include "defs.h"
+
+static int in_wpt;
+static int in_rte;
+static int in_ele;
+static int in_name;
+static int in_time;
+static int in_desc;
+
+static XML_Parser psr;
+
+static const char *gpx_version;
+static const char *gpx_creator;
+
+static waypoint *wpt_tmp;
+static FILE *fd;
+static FILE *ofd;
+
+static void
+tag_gpx(const char **attrv)
+{
+ const char **avp = &attrv[0];
+ while (*avp) {
+ if (strcmp(avp[0], "version") == 0) {
+ gpx_version = avp[1];
+ }
+ else if (strcmp(avp[0], "src") == 0) {
+ gpx_creator = avp[1];
+ }
+ avp+=2;
+ }
+}
+
+static void
+tag_wpt(const char **attrv)
+{
+ const char **avp = &attrv[0];
+
+ wpt_tmp = calloc(sizeof(*wpt_tmp), 1);
+ if (wpt_tmp == NULL) {
+ fatal("Can not allocate memory\n");
+ }
+
+ while (*avp) {
+ if (strcmp(avp[0], "lat") == 0) {
+ sscanf(avp[1], "%lf",
+ &wpt_tmp->position.latitude.degrees);
+ }
+ else if (strcmp(avp[0], "lon") == 0) {
+ sscanf(avp[1], "%lf",
+ &wpt_tmp->position.longitude.degrees);
+ }
+ avp+=2;
+ }
+}
+
+static void
+gpx_start(void *data, const char *el, const char **attr)
+{
+
+ if (strcmp(el, "ele") == 0) {
+ in_ele++;
+ } if (strcmp(el, "name") == 0) {
+ in_name ++;
+ } if (strcmp(el, "gpx") == 0) {
+ tag_gpx(attr);
+ } if (strcmp(el, "wpt") == 0) {
+ in_wpt++;
+ tag_wpt(attr);
+ } if (strcmp(el, "desc") == 0) {
+ in_desc++;
+ } if (strcmp(el, "rtept") == 0) {
+ in_rte++;
+ tag_wpt(attr);
+ } if (strcmp(el, "time") == 0) {
+ in_time++;
+ }
+}
+
+static void
+gpx_end(void *data, const char *el)
+{
+ if (strcmp(el, "wpt") == 0) {
+ waypt_add(wpt_tmp);
+ in_wpt--;
+ }
+ else if (strcmp(el, "rtept") == 0) {
+ route_add(wpt_tmp);
+ in_rte--;
+ } else if (strcmp(el, "name") == 0) {
+ in_name--;
+ } else if (strcmp(el, "desc") == 0) {
+ in_desc--;
+ } else if (strcmp(el, "ele") == 0) {
+ in_ele--;
+ } else if (strcmp(el, "time") == 0) {
+ in_time--;
+ }
+}
+
+static void
+gpx_cdata(void *dta, const XML_Char *s, int len)
+{
+ char *foo = malloc(len+1);
+ foo[len] = 0;
+ strncpy(foo, s, len);
+ if (in_name && in_wpt) {
+ wpt_tmp->shortname = foo;
+ }
+ if (in_desc) {
+ wpt_tmp->description = foo;
+ }
+ if (in_ele) {
+ sscanf(foo, "%lf",
+ &wpt_tmp->position.altitude.altitude_meters);
+ }
+ if (in_time && (in_wpt || in_rte)) {
+ struct tm tm;
+ sscanf(foo, "%d-%d-%dT%d:%d:%dZ\n",
+ &tm.tm_year,
+ &tm.tm_mon,
+ &tm.tm_mday,
+ &tm.tm_hour,
+ &tm.tm_min,
+ &tm.tm_sec);
+ tm.tm_mon -= 1;
+ tm.tm_year -= 1900;
+ tm.tm_isdst = 1;
+ wpt_tmp->creation_time = mktime(&tm);
+ }
+}
+
+void
+gpx_rd_init(const char *fname)
+{
+ fd = fopen(fname, "r");
+ if (fd == NULL) {
+ fatal("GPX: Cannot open %s for reading\n", fname );
+ }
+ psr = XML_ParserCreate(NULL);
+ if (!psr) {
+ fatal("GPX: Cannot create XML Parser\n");
+ }
+ XML_SetElementHandler(psr, gpx_start, gpx_end);
+ XML_SetCharacterDataHandler(psr, gpx_cdata);
+}
+
+static void
+gpx_rd_deinit(void)
+{
+ fclose(fd);
+}
+
+void
+gpx_wr_init(const char *fname)
+{
+ ofd = fopen(fname, "w");
+ if (ofd == NULL) {
+ fatal("GPX: Cannot open %s for writing\n", fname );
+ }
+}
+
+static void
+gpx_wr_deinit(void)
+{
+ fclose(ofd);
+}
+void
+gpx_read(void)
+{
+ int len;
+ int done = 0;
+ char buf[102400];
+
+ while (!done) {
+ len = fread(buf, 1, sizeof(buf), fd);
+ done = feof(fd);
+ if (!XML_Parse(psr, buf, len, done)) {
+ fatal("GPX: XML parse error at %d: %s\n",
+ XML_GetCurrentLineNumber(psr),
+ XML_ErrorString(XML_GetErrorCode(psr)));
+ }
+ }
+}
+
+static void
+gpx_waypt_pr(waypoint *waypointp)
+{
+
+ fprintf(ofd, "<wpt lat=\"%lf\" lon=\"%lf\">\n",
+ waypointp->position.latitude.degrees,
+ waypointp->position.longitude.degrees);
+ fprintf(ofd, "<name>%s</name>\n", waypointp->shortname);
+ fprintf(ofd, "<desc>");
+ fprintf(ofd, "<![CDATA[%s]]>", waypointp->description);
+ fprintf(ofd, "</desc>\n");
+ if (waypointp->position.altitude.altitude_meters) {
+ fprintf(ofd, "<ele>\n%f\n</ele>\n",
+ waypointp->position.altitude.altitude_meters);
+ }
+ if (waypointp->url) {
+ fprintf(ofd, "<url>%s</url>\n", waypointp->url);
+ }
+ if (waypointp->url_link_text) {
+ fprintf(ofd, "<urlname>%s</urlname>\n",
+ waypointp->url_link_text);
+ }
+ fprintf(ofd, "</wpt>\n");
+}
+
+void
+gpx_write(void)
+{
+ fprintf(ofd, "<?xml version=\"1.0\"?>\n");
+ fprintf(ofd, "<gpx\n\tversion=\"1.0\">\n");
+ waypt_disp_all(gpx_waypt_pr);
+ fprintf(ofd, "</gpx>\n");
+}
+
+ff_vecs_t gpx_vecs = {
+ gpx_rd_init,
+ gpx_wr_init,
+ gpx_rd_deinit,
+ gpx_wr_deinit,
+ gpx_read,
+ gpx_write,
+};
--- /dev/null
+/*
+ Copyright (C) 2002 Robert Lipe, robertlipe@usa.net
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
+
+ */
+
+/*
+ * Table of "interesting" Magellan models.
+ * Selfishly, if I haven't heard of it, it's not in the table.
+ * This doesn't mean I actually have TRIED all models listed below.
+ * (Donations welcome. :-)
+ */
+typedef enum {
+ mm_unknown,
+ mm_gps315320,
+ mm_map410,
+ mm_map330,
+ mm_gps310,
+ mm_meridian
+} meridian_model;
+
+typedef struct pid_to_model {
+ meridian_model model;
+ int pid;
+ const char *model_n;
+} pid_to_model_t;
+
+typedef struct icon_mapping {
+ const char *token;
+ const char *icon;
+} icon_mapping_t;
+
+const char * mag_find_descr_from_token(const char *token);
+const char * mag_find_token_from_descr(const char *icon);
--- /dev/null
+/*
+ Communicate Thales/Magellan serial protocol.
+
+ Copyright (C) 2002 Robert Lipe, robertlipe@usa.net
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
+
+ */
+
+#include <termios.h>
+#include <ctype.h>
+
+#include "defs.h"
+#include "magellan.h"
+
+#define debug 1
+
+typedef enum {
+ mrs_handoff = 0,
+ mrs_handon
+} mag_rxstate;
+
+static FILE *magfile;
+static int magfd;
+static mag_rxstate magrxstate;
+static struct termios orig_tio;
+static int last_rx_csum;
+static int found_done;
+static icon_mapping_t *icon_mapping;
+
+static waypoint * mag_wptparse(char *);
+
+static icon_mapping_t gps315_icon_table[] = {
+ { "a", "filled circle" },
+ { "b", "box" },
+ { "c", "red buoy" },
+ { "d", "green buoy" },
+ { "e", "buoy" },
+ { "f", "rocks" },
+ { "g", "red daymark" },
+ { "h", "green daymark" },
+ { "i", "bell" },
+ { "j", "danger" },
+ { "k", "diver down" },
+ { "l", "fish" },
+ { "m", "house" },
+ { "n", "mark" },
+ { "o", "car" },
+ { "p", "tent" },
+ { "q", "boat" },
+ { "r", "food" },
+ { "s", "fuel" },
+ { "t", "tree" },
+ { NULL, NULL }
+};
+
+static icon_mapping_t map330_icon_table[] = {
+ { "a", "crossed square" },
+ { "b", "box" },
+ { "c", "house" },
+ { "d", "aerial" },
+ { "e", "airport" },
+ { "f", "amusement park" },
+ { "g", "ATM" },
+ { "h", "auto repair" },
+ { "i", "boating" },
+ { "j", "camping" },
+ { "k", "exit ramp" },
+ { "l", "first aid" },
+ { "m", "nav aid" },
+ { "n", "buoy" },
+ { "o", "fuel" },
+ { "p", "garden" },
+ { "q", "golf" },
+ { "r", "hotel" },
+ { "s", "hunting/fishing" },
+ { "t", "large city" },
+ { "u", "lighthouse" },
+ { "v", "major city" },
+ { "w", "marina" },
+ { "x", "medium city" },
+ { "y", "museum" },
+ { "z", "obstruction" },
+ { "aa", "park" },
+ { "ab", "resort" },
+ { "ac", "restaraunt" },
+ { "ad", "rock" },
+ { "ae", "scuba" },
+ { "af", "RV service" },
+ { "ag", "shooting" },
+ { "ah", "sight seeing" },
+ { "ai", "small city" },
+ { "aj", "sounding" },
+ { "ak", "sports arena" },
+ { "al", "tourist info" },
+ { "am", "truck service" },
+ { "an", "winery" },
+ { "ao", "wreck" },
+ { "ap", "zoo" },
+ { NULL, NULL }
+};
+
+pid_to_model_t pid_to_model[] =
+{
+ { mm_gps315320, 24, "GPS 315/320" },
+ { mm_map410, 25, "Map 410" },
+ { mm_map330, 30, "Map 330" },
+ { mm_gps310, 31, "GPS 310" },
+ { mm_meridian, 33, "Meridian" },
+ { 0, 0, NULL }
+};
+
+
+/*
+ * Given a protocol message, compute the checksum as needed by
+ * the Magellan protocol.
+ */
+static unsigned int
+mag_checksum(const char * const buf)
+{
+ int csum = 0;
+ const char *p;
+
+ for(p = buf; *p; p++) {
+ csum ^= *p;
+ }
+
+ return csum;
+}
+static unsigned int
+mag_pchecksum(const char * const buf, int len)
+{
+ int csum = 0;
+ const char *p = buf;
+ for (; len ; len--) {
+ csum ^= *p++;
+ }
+ return csum;
+}
+
+static void
+mag_writemsg(const char * const buf)
+{
+ unsigned int osum = mag_checksum(buf);
+
+ if (debug) {
+ fprintf(stderr,"WRITE: $%s*%02X\r\n",buf, osum);
+ }
+#if 0
+ retry:
+#endif
+ fprintf(magfile, "$%s*%02X\r\n",buf, osum);
+#if 0
+ if (magrxstate == mrs_handon) {
+ mag_readmsg();
+ if (last_rx_csum != osum) {
+fprintf(stderr, "E");
+ goto retry;
+ }
+ }
+#endif
+}
+static void
+mag_writeack(int osum)
+{
+ char obuf[100];
+ snprintf(obuf, sizeof(obuf), "PMGNCSM,%02X", osum);
+ mag_writemsg(obuf);
+}
+
+static void
+mag_handon(void)
+{
+ magrxstate = mrs_handon;
+ mag_writemsg("PMGNCMD,HANDON");
+}
+
+static void
+mag_handoff(void)
+{
+ magrxstate = mrs_handoff;
+ mag_writemsg("PMGNCMD,HANDOFF");
+}
+
+void
+mag_verparse(char *ibuf)
+{
+ int prodid = mm_unknown;
+ char version[1024];
+ pid_to_model_t *pp = pid_to_model;
+ sscanf(ibuf,"$PMGNVER,%d,%[^,]", &prodid, version);
+
+ for (pp = pid_to_model; pp->model ; pp++) {
+ if (pp->pid == prodid) {
+ break;
+ }
+ }
+ switch (pp->model) {
+ case mm_gps315320:
+ case mm_map410:
+ icon_mapping = gps315_icon_table;
+ break;
+ case mm_map330:
+ case mm_meridian:
+ icon_mapping = map330_icon_table;
+ break;
+ default:
+ abort();
+ }
+}
+
+#define IS_TKN(x) (strncmp(ibuf,x, sizeof(x)-1) == 0)
+
+static void
+mag_readmsg(void)
+{
+ char ibuf[100];
+ int isz;
+ unsigned int isum;
+ char *isump;
+ fgets(ibuf, sizeof(ibuf), magfile);
+ isz = strlen(ibuf);
+ if (isz < 5) {
+if (debug)
+fprintf(stderr, "SHORT READ %d\n", isz);
+ return;
+ }
+ while (!isprint(ibuf[isz]))
+ isz--;
+ isump = &ibuf[isz-1];
+ isum = strtoul(isump, NULL,16);
+ if (isum != mag_pchecksum(&ibuf[1], isz-3)) {
+if (debug)
+ fprintf(stderr, "RXERR %02x/%02x: '%s'\n", isum, mag_pchecksum(&ibuf[1],isz-5), ibuf);
+ }
+if (debug)
+fprintf(stderr, "READ: %s\n", ibuf);
+ if (IS_TKN("$PMGNCSM,")) {
+ last_rx_csum = strtoul(&ibuf[9], NULL, 16);
+ return;
+ }
+ if (strncmp(ibuf, "$PMGNWPT,", 7) == 0) {
+ waypoint *wpt = mag_wptparse(ibuf);
+ waypt_add(wpt);
+ }
+ if (IS_TKN("$PMGNVER,")) {
+ mag_verparse(ibuf);
+return;
+ }
+ if (IS_TKN("$PMGNCMD,END")) {
+ found_done = 1;
+return;
+ }
+ mag_writeack(isum);
+}
+
+static void
+mag_rd_init(const char *portname)
+{
+ struct termios new_tio;
+ magfile = fopen(portname, "rw+b");
+
+ if (magfile == NULL) {
+ perror("Open failed");
+ return;
+ }
+
+ magfd = fileno(magfile);
+ tcgetattr(magfd, &orig_tio);
+ new_tio = orig_tio;
+ new_tio.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|
+ IXON);
+ new_tio.c_oflag &= ~OPOST;
+ new_tio.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
+ new_tio.c_cflag &= ~(CSIZE|PARENB);
+ new_tio.c_cflag |= CS8;
+
+ cfsetospeed(&new_tio, B4800);
+ cfsetispeed(&new_tio, B4800);
+ tcsetattr(magfd, TCSAFLUSH, &new_tio);
+
+ mag_handon();
+ mag_writemsg("PMGNCMD,VERSION");
+ mag_writemsg("PMGNCMD,NMEAOFF");
+ return;
+}
+
+static void
+mag_deinit(void)
+{
+ mag_handoff();
+ tcsetattr(magfd, TCSANOW, &orig_tio);
+ fclose(magfile);
+}
+
+/*
+ * Given an incoming track messages of the form:
+ * $PMGNTRK,3605.259,N,08644.389,W,00151,M,201444.61,A,,020302*66
+ * create and return a populated waypoint.
+ */
+waypoint *
+mag_trkparse(char *trkmsg)
+{
+ double latdeg, lngdeg;
+ int alt;
+ char altunits;
+ char lngdir, latdir;
+ int dmy;
+ int hms;
+ int fracsecs;
+ struct tm tm;
+ waypoint *waypt;
+
+ waypt = calloc(sizeof *waypt, 1);
+ if (waypt == NULL)
+ return NULL;
+
+ printf("%s\n", trkmsg);
+ memset(&tm, 0, sizeof(tm));
+#if 0
+ sscanf(trkmsg,"$PMGNTRK,%lf,%c,%lf,%c,%d,%c,%d.%d,A,,%d",
+ &latdeg,&latdir,
+ &lngdeg,&lngsecs,&lngdir,
+ &alt,&altunits,&hms,&fracsecs,&dmy);
+#else
+latdeg = 123;
+#endif
+
+ tm.tm_sec = hms % 100;
+ hms = hms / 100;
+ tm.tm_min = hms % 100;
+ hms = hms / 100;
+ tm.tm_hour = hms % 100;
+
+ tm.tm_mon = dmy % 100;
+ dmy = dmy / 100;
+ tm.tm_mday = dmy % 100;
+ dmy = dmy / 100;
+ tm.tm_year = 100 + dmy % 100;
+
+ /*
+ * FIXME: mktime assumes the struct tm is in local time, which
+ * ours is not...
+ */
+ waypt->time_created = mktime(&tm);
+
+ waypt->position.latitude.degrees = latdeg / 100.0;
+ waypt->position.longitude.degrees = lngdeg / 100.0;
+ waypt->position.altitude.altitude_meters = alt;
+
+ return waypt;
+
+}
+
+const char *
+mag_find_descr_from_token(const char *token)
+{
+ icon_mapping_t *i = icon_mapping;
+
+ if (icon_mapping == NULL) {
+ return "unknown";
+ }
+
+ for (i = icon_mapping; i->token; i++) {
+ if (strcmp(token, i->token) == 0)
+ return i->icon;
+ }
+ return icon_mapping[0].icon;
+}
+
+const char *
+mag_find_token_from_descr(const char *icon)
+{
+ icon_mapping_t *i = icon_mapping;
+
+ if (i == NULL || icon == NULL) {
+ return "a";
+ }
+
+ for (i = icon_mapping; i->token; i++) {
+ if (strcmp(icon, i->icon) == 0)
+ return i->token;
+ }
+ return icon_mapping[0].token;
+}
+
+
+/*
+ * Given an incoming waypoint messages of the form:
+ * $PMGNWPL,3549.499,N,08650.827,W,0000257,M,HOME,HOME,c*4D
+ * create and return a populated waypoint.
+ */
+waypoint *
+mag_wptparse(char *trkmsg)
+{
+ double latdeg, lngdeg;
+ char latdir;
+ char lngdir;
+ int alt;
+ char altunits;
+ char shortname[100];
+ char descr[100];
+ char icon_token[100];
+ waypoint *waypt;
+ char *icons;
+ char *icone;
+ char *blah;
+ int i = 0;
+
+ descr[0] = 0;
+ icon_token[0] = 0;
+
+ waypt = calloc(sizeof *waypt, 1);
+ if (waypt == NULL)
+ fatal("Magproto: Cannot allocate memory\n");
+
+ sscanf(trkmsg,"$PMGNWPL,%lf,%c,%lf,%c,%d,%c,%[^,],%[^,]",
+ &latdeg,&latdir,
+ &lngdeg,&lngdir,
+ &alt,&altunits,shortname,descr);
+ icone = strrchr(trkmsg, '*');
+ icons = strrchr(trkmsg, ',')+1;
+
+ for (blah = icons ; blah < icone; blah++)
+ icon_token[i++] = *blah;
+
+ if (latdir == 'S') latdeg = -latdeg;
+ waypt->position.latitude.degrees = latdeg / 100.0;
+
+ if (lngdir == 'W') lngdeg = -lngdeg;
+ waypt->position.longitude.degrees = lngdeg / 100.0;
+
+ waypt->position.altitude.altitude_meters = alt;
+ waypt->shortname = strdup(shortname);
+ waypt->description = strdup(descr);
+ waypt->icon_descr = mag_find_descr_from_token(icon_token);
+
+ return waypt;
+}
+
+#if BLERF
+
+int main(void)
+{
+char trk1[] = "$PMGNTRK,3605.259,N,08644.389,W,00151,M,201444.61,A,,020302*66";
+char trk2[] = "$PMGNTRK,3605.315,N,08644.625,W,00153,M,211618.68,A,,020302*6D";
+char trk3[] = "$PMGNTRK,3605.320,N,08644.619,W,00164,M,212121.87,A,,020302*6F";
+char wpt1[] = "$PMGNWPL,3604.831,N,08659.737,W,0000000,M,PowerPln,Power Plant by White Dog Pack,a*50";
+char wpt2[] = "$PMGNWPL,3614.645,N,08641.885,W,0000000,M,CmbrlndR,Cumberland River Cache by GISG,a*7B";
+char wpt3[] = "$PMGNWPL,3608.210,N,08648.389,W,0000000,M,Puff!,Puff! by White Dog Pack,a*61";
+waypt_init();
+route_init();
+
+#if 1
+mag_trkparse(trk1);
+mag_trkparse(trk2);
+mag_trkparse(trk3);
+
+exit(0);
+#endif
+
+#if 1
+mag_wptparse(wpt1);
+mag_wptparse(wpt2);
+mag_wptparse(wpt3);
+exit(0);
+#endif
+ mag_init();
+
+#if 1
+ mag_writemsg("PMGNCMD,WAYPOINT");
+while (!found_done) {
+ mag_readmsg();
+}
+exit(0);
+#endif
+#if 0
+ mag_writemsg("PMGNCMD,TRACK,2");
+while (!found_done) {
+ mag_readmsg();
+}
+#endif
+#if 1
+ mag_writemsg("PMGNCMD,ROUTE");
+while (!found_done) {
+ mag_readmsg();
+}
+exit(0);
+#endif
+#if 0
+ mag_writemsg("PMGNCMD,FIL,FIRST,?");
+sleep(2);
+ mag_readmsg();
+while (!found_done) {
+ mag_writemsg("PMGNCMD,FIL,NEXT");
+ mag_readmsg();
+sleep(2);
+}
+#endif
+ mag_deinit();
+ return 0;
+}
+
+#if SOON
+/* ROUTES */
+READ: $PMGNRTE,3,1,c,19,HOME,c,KidsAtPl,a*0F
+READ: $PMGNRTE,3,2,c,19,TrainWrc,a,Leipers,a*6F
+READ: $PMGNRTE,3,3,c,19,Nashvill,a,HOME,c*1A
+
+/* WAYPOINTS */
+READ: $PMGNWPL,3604.831,N,08659.737,W,0000000,M,PowerPln,Power Plant by White Do
+READ: $PMGNWPL,3614.645,N,08641.885,W,0000000,M,CmbrlndR,Cumberland River Cache
+READ: $PMGNWPL,3608.210,N,08648.389,W,0000000,M,Puff!,Puff! by White Dog Pack,a*
+61
+
+#endif
+#endif
+
+void
+mag_readwpt(void)
+{
+ mag_writemsg("PMGNCMD,WAYPOINT");
+ while (!found_done) {
+ mag_readmsg();
+ }
+}
+
+static
+void
+mag_waypt_pr(waypoint *waypointp)
+{
+ double lon, lat;
+ double ilon, ilat;
+ char obuf[200];
+ ilat = waypointp->position.latitude.degrees;
+ ilon = waypointp->position.longitude.degrees;
+
+ lon =fabs(ilon * 100.0);
+ lat =fabs(ilat * 100.0);
+
+ sprintf(obuf, "PMGNWPL,%4.3f,%c,%05.3f,%c,%.lf,M,%-.8s,%-.20s,%s",
+ lat, ilon < 0 ? 'N' : 'S',
+ lon, ilat < 0 ? 'E' : 'W',
+ waypointp->position.altitude.altitude_meters,
+ waypointp->shortname,
+ waypointp->description,
+ waypointp->icon_descr);
+ mag_writemsg(obuf);
+ mag_readmsg();
+}
+
+
+void
+mag_write(void)
+{
+#if 1
+ mag_readmsg();
+ mag_readmsg();
+ mag_readmsg();
+ mag_readmsg();
+#endif
+ waypt_disp_all(mag_waypt_pr);
+
+}
+
+ff_vecs_t mag_vecs = {
+ mag_rd_init,
+ mag_rd_init,
+ mag_deinit,
+ mag_deinit,
+ mag_readwpt,
+ mag_write,
+};
--- /dev/null
+/*
+ Copyright (C) 2002 Robert Lipe, robertlipe@usa.net
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
+
+ */
+
+
+#include "defs.h"
+#include <unistd.h>
+
+void
+usage(const char *pname)
+{
+ printf("Usage: %s -i <INPUT_FILE_TYPE> -f <INPUT_FILE> -o <OUT FTYPE> -F <OUTPUT_FILE>\n", pname);
+ printf("Supported file types:\n");
+ disp_vecs();
+}
+
+int
+main(int argc, char *argv[])
+{
+ int c;
+ ff_vecs_t *ivecs = NULL;
+ ff_vecs_t *ovecs = NULL;
+ char *fname = NULL;
+ char *ofname = NULL;
+
+ waypt_init();
+ route_init();
+
+ while (( c = getopt(argc, argv, "?hi:o:f:F:")) != EOF) {
+ switch (c) {
+ case 'i':
+ ivecs = find_vec(optarg);
+ break;
+ case 'o':
+ ovecs = find_vec(optarg);
+ break;
+ case 'f':
+ fname = optarg;
+ if (ivecs == NULL) {
+ fatal ("No valid input type specified");
+ }
+ ivecs->rd_init(fname);
+ ivecs->read();
+ break;
+ case 'F':
+ ofname = optarg;
+ if (ovecs) {
+ ovecs->wr_init(ofname);
+ ovecs->write();
+ }
+ break;
+ case 'h':
+ case '?':
+ usage(argv[0]);
+ exit(0);
+ }
+ }
+
+ if (ovecs == NULL)
+ waypt_disp_all(waypt_disp);
+
+ exit(0);
+}
--- /dev/null
+/*
+ Access Magellan Mapsend files.
+
+ Copyright (C) 2002 Robert Lipe, robertlipe@usa.net
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "defs.h"
+#include "mapsend.h"
+
+static FILE *mapsend_file_in;
+static FILE *mapsend_file_out;
+
+static void
+mapsend_rd_init(const char *fname)
+{
+ mapsend_file_in = fopen(fname, "r");
+ if (mapsend_file_in == NULL) {
+ fprintf(stderr, "Cannot open '%s' for reading\n", fname);
+ exit(1);
+ }
+}
+
+static void
+mapsend_rd_deinit(void)
+{
+ fclose(mapsend_file_in);
+}
+
+static void
+mapsend_wr_init(const char *fname)
+{
+ mapsend_file_out = fopen(fname, "w");
+ if (mapsend_file_out == NULL) {
+ fprintf(stderr, "Cannot open '%s' for writing\n", fname);
+ exit(1);
+ }
+}
+
+static void
+mapsend_wr_deinit(void)
+{
+ fclose(mapsend_file_out);
+}
+
+static void
+mapsend_read(void)
+{
+ mapsend_hdr hdr;
+ char tbuf[256];
+ char name[257];
+ char comment[257];
+ char *p;
+ int wpt_count;
+ unsigned char scount;
+ int wpt_number;
+ char wpt_icon;
+ char wpt_status;
+ double wpt_alt;
+ double wpt_long;
+ double wpt_lat;
+ waypoint *wpt_tmp;
+
+ /*
+ * Becuase of the silly struct packing and the goofy variable-length
+ * strings, each member has to be read in one at a time. Grrr.
+ */
+
+ fread(&hdr, sizeof(hdr), 1, mapsend_file_in);
+
+ fread(&wpt_count, sizeof(wpt_count), 1, mapsend_file_in);
+
+ while (wpt_count--) {
+ wpt_tmp = calloc(sizeof(*wpt_tmp), 1);
+
+ fread(&scount, sizeof(scount), 1, mapsend_file_in);
+ fread(&tbuf, scount, 1, mapsend_file_in);
+ p = strncpy(name, tbuf, scount);
+ p[scount] = '\0';
+
+ fread(&scount, sizeof(scount), 1, mapsend_file_in);
+ fread(&tbuf, scount, 1, mapsend_file_in);
+ p = strncpy(comment, tbuf, scount);
+ p[scount] = '\0';
+
+ fread(&wpt_number, sizeof(wpt_number), 1, mapsend_file_in);
+ fread(&wpt_icon, sizeof(wpt_icon), 1, mapsend_file_in);
+ fread(&wpt_status, sizeof(wpt_status), 1, mapsend_file_in);
+ fread(&wpt_alt, sizeof(wpt_alt), 1, mapsend_file_in);
+ fread(&wpt_long, sizeof(wpt_long), 1, mapsend_file_in);
+ fread(&wpt_lat, sizeof(wpt_lat), 1, mapsend_file_in);
+
+ wpt_tmp->shortname = strdup(name);
+ wpt_tmp->description = strdup(comment);
+ wpt_tmp->position.altitude.altitude_meters = wpt_alt;
+ wpt_tmp->position.latitude.degrees = -wpt_lat;
+ wpt_tmp->position.longitude.degrees = wpt_long;
+
+ waypt_add(wpt_tmp);
+ }
+}
+
+static void
+mapsend_waypt_pr(waypoint *waypointp)
+{
+ int n;
+ double falt;
+ double flong;
+ double flat;
+static int cnt = 0;
+
+ n = strlen(waypointp->shortname);
+ fwrite(&n, 1, 1, mapsend_file_out);
+ fwrite(waypointp->shortname, n, 1, mapsend_file_out);
+
+ n = strlen(waypointp->description);
+ fwrite(&n, 1, 1, mapsend_file_out);
+ fwrite(waypointp->description, n, 1, mapsend_file_out);
+
+ /* #, icon, status */
+n = ++cnt;
+ fwrite(&n, 4, 1, mapsend_file_out);
+n = 0;
+ fwrite(&n, 1, 1, mapsend_file_out);
+n = 1;
+ fwrite(&n, 1, 1, mapsend_file_out);
+
+ falt = waypointp->position.altitude.altitude_meters;
+ fwrite(&falt, sizeof(double), 1, mapsend_file_out);
+
+ flong = waypointp->position.longitude.degrees;
+ fwrite(&flong, sizeof(double), 1, mapsend_file_out);
+ flat = -waypointp->position.latitude.degrees;
+ fwrite(&flat, sizeof(double), 1, mapsend_file_out);
+}
+
+void
+mapsend_write(void)
+{
+ mapsend_hdr hdr = {13, "4D533330 MS", "30", 1};
+ int wpt_count = waypt_count();
+int n = 0;
+
+ fwrite(&hdr, sizeof(hdr), 1, mapsend_file_out);
+ fwrite(&wpt_count, sizeof(wpt_count), 1, mapsend_file_out);
+
+ waypt_disp_all(mapsend_waypt_pr);
+
+ fwrite(&n, 4, 1, mapsend_file_out);
+/* TODO: Impelment routes here */
+}
+
+ff_vecs_t mapsend_vecs = {
+ mapsend_rd_init,
+ mapsend_wr_init,
+ mapsend_rd_deinit,
+ mapsend_wr_deinit,
+ mapsend_read,
+ mapsend_write,
+};
--- /dev/null
+/*
+ Access to MapSend files.
+
+ Copyright (C) 2002 Robert Lipe, robertlipe@usa.net
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
+
+ *
+ * Information from:
+ * Mapsend File Format Description Revision 1.1, March 6, 2002 from Thales.
+ *
+ * Note this file format was clearly NOT designed for cross-architecture
+ * portability. In fact, becuase of the pascal nature of the 'string'
+ * data type described in that document, it's impractical to describe
+ * a 'struct waypoint' in C.
+ *
+ */
+
+typedef struct {
+ char ms_length;
+ char ms_signature[11];
+ char ms_version[2];
+ char ms_type;
+ char _ms_type[3];
+} mapsend_hdr;
--- /dev/null
+/*
+ Acess to Garmin MapSource files.
+
+ Copyright (C) 2002 Robert Lipe, robertlipe@usa.net
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "defs.h"
+#include <ctype.h>
+
+static FILE *mapsource_file_in;
+static FILE *mapsource_file_out;
+
+static void
+mapsource_rd_init(const char *fname)
+{
+ mapsource_file_in = fopen(fname, "r");
+ if (mapsource_file_in == NULL) {
+ fprintf(stderr, "Cannot open '%s' for reading\n", fname);
+ exit(1);
+ }
+}
+
+static void
+mapsource_rd_deinit(void)
+{
+ fclose(mapsource_file_in);
+}
+
+static void
+mapsource_wr_init(const char *fname)
+{
+ mapsource_file_out = fopen(fname, "w");
+ if (mapsource_file_out == NULL) {
+ fprintf(stderr, "Cannot open '%s' for writing\n", fname);
+ exit(1);
+ }
+}
+
+static void
+mapsource_wr_deinit(void)
+{
+ fclose(mapsource_file_out);
+}
+
+static void
+mapsource_read(void)
+{
+ char name[9], date[20], timeb[20];
+ char ibuf[200];
+ double lat,lon;
+ char latdir, londir;
+ int latd, lond;
+ float latf, lonf;
+ int alt;
+ char altunits[10];
+ char icon[20];
+ waypoint *wpt_tmp;
+
+ while (fgets(ibuf, sizeof(ibuf), mapsource_file_in)) {
+ sscanf(ibuf,
+ "Waypoint %s %s %s %c%d %f %c%d %f %d %s Symbol & Name %s",
+ name, date, timeb, &latdir, &latd, &latf, &londir, &lond, &lonf, &alt, altunits, icon);
+ wpt_tmp = calloc(sizeof(*wpt_tmp),1);
+ if (wpt_tmp == NULL) {
+ fatal("MAPSOURCE: cannot allocate memory\n");
+ }
+/* FIXME: Implement actual appropriate conversion */
+ wpt_tmp->position.altitude.altitude_meters = alt * 3.0;
+ wpt_tmp->shortname = strdup(name);
+ wpt_tmp->description = strdup(name);
+
+ lat = latd + latf/100.0;
+ lon = lond + lonf/100.0;
+ if (latdir == 'S') lat = -lat;
+ if (londir == 'W') lon = -lon;
+ wpt_tmp->position.latitude.degrees = lat;
+ wpt_tmp->position.longitude.degrees = lon;
+
+ waypt_add(wpt_tmp);
+ }
+}
+
+static void
+mapsource_waypt_pr(waypoint *waypointp)
+{
+ char tbuf[1024];
+ char *tp = tbuf;
+ int d;
+ strftime(tbuf, sizeof(tbuf), "%d-%b-%y %I:%M:%S%p", localtime(&waypointp->creation_time));
+ while (*tp) {
+ *tp = toupper(*tp);
+ tp++;
+ }
+/* FIXME: cure the sign dependencies here. */
+ fprintf(mapsource_file_out, "Waypoint %s %s ", waypointp->shortname, tbuf);
+ fprintf(mapsource_file_out, "N%02.0f", waypointp->position.latitude.degrees);
+ d = waypointp->position.latitude.degrees;
+ fprintf(mapsource_file_out, " %06.3f ", (waypointp->position.latitude.degrees - d) * 100);
+ fprintf(mapsource_file_out, "W%02.0f", fabs(waypointp->position.longitude.degrees));
+ d = fabs(waypointp->position.longitude.degrees);
+ fprintf(mapsource_file_out, " %06.3f ", (fabs(waypointp->position.longitude.degrees) - d) * 100);
+ fprintf(mapsource_file_out, "0 ft Symbol & Name Unknown\n");
+}
+
+void
+mapsource_write(void)
+{
+ waypt_disp_all(mapsource_waypt_pr);
+
+}
+
+ff_vecs_t mapsource_vecs = {
+ mapsource_rd_init,
+ mapsource_wr_init,
+ mapsource_rd_deinit,
+ mapsource_wr_deinit,
+ mapsource_read,
+ mapsource_write,
+};
--- /dev/null
+/*
+ Access to Garmin PCX5 files.
+
+ Copyright (C) 2002 Robert Lipe, robertlipe@usa.net
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
+*/
+
+
+#include "defs.h"
+#include <ctype.h>
+
+static FILE *file_in;
+static FILE *file_out;
+
+static void
+rd_init(const char *fname)
+{
+ file_in = fopen(fname, "r");
+ if (file_in == NULL) {
+ fatal("GPSUTIL: Cannot open %s for reading\n", fname);
+ }
+}
+
+static void
+rd_deinit(void)
+{
+ fclose(file_in);
+}
+
+static void
+wr_init(const char *fname)
+{
+ file_out = fopen(fname, "w");
+ if (file_out == NULL) {
+ fatal("GPSUTIL: Cannot open %s for writing\n", fname);
+ }
+}
+
+static void
+wr_deinit(void)
+{
+ fclose(file_out);
+}
+
+static void
+data_read(void)
+{
+ char name[9], desc[90];
+ double lat,lon;
+ char latdir, londir;
+ long alt;
+ char alttype;
+ char icon[3] = {0};
+ char date[10];
+ char time[9];
+ waypoint *wpt_tmp;
+ char ibuf[100];
+
+ for(;fgets(ibuf, sizeof(ibuf), file_in);) {
+ switch (ibuf[0]) {
+ case 'W':
+ sscanf(ibuf, "W %s %c%lf %c%lf %s %s %ld %90[^\n']",
+ name, &latdir, &lat, &londir, &lon,
+ date, time, &alt, desc);
+ wpt_tmp = calloc(sizeof(*wpt_tmp), 1);
+ wpt_tmp->position.altitude.altitude_meters = alt;
+ wpt_tmp->shortname = strdup(name);
+ wpt_tmp->description = strdup(desc);
+
+ if (latdir == 'S') lat = -lat;
+ if (londir == 'W') lon = -lon;
+ wpt_tmp->position.longitude.degrees = lon/100.0;
+ wpt_tmp->position.latitude.degrees = lat/100.0;
+ wpt_tmp->icon_descr = strdup(icon);
+ waypt_add(wpt_tmp);
+ }
+ }
+}
+
+static void
+gpsutil_disp(waypoint *wpt)
+{
+ double lon,lat;
+ signed int ilon, ilat;
+ const char *icon_token = "0";
+ char tbuf[1024];
+ char *tp = tbuf;
+ time_t tm = wpt->creation_time;
+
+ ilon = (signed int)wpt->position.longitude.degrees;
+ ilat = (signed int)wpt->position.latitude.degrees;
+ lon = (ilon * 100.0) + (wpt->position.longitude.degrees - ilon) * 60.0;
+ lat = (ilat * 100.0) + (wpt->position.latitude.degrees - ilat) * 60.0;
+
+ if (tm == 0)
+ tm = time(NULL);
+ strftime(tbuf, sizeof(tbuf), "%d-%b-%y %I:%M:%S", localtime(&tm));
+ while (*tp) {
+ *tp = toupper(*tp);
+ tp++;
+ }
+
+ fprintf(file_out, "W %-6.6s %c%08.5f %c%011.5f %s %5d %-40.40s %5e %s\n",
+ wpt->shortname,
+ lat < 0.0 ? 'S' : 'N',
+ fabs(lat),
+ lon < 0.0 ? 'W' : 'E',
+ fabs(lon),
+ tbuf,
+ -9999,
+ wpt->description,
+ 0.0,
+ icon_token);
+}
+
+static void
+data_write(void)
+{
+fprintf(file_out,
+"H SOFTWARE NAME & VERSION\n"
+"I PCX5 2.09\n"
+"\n"
+"H R DATUM IDX DA DF DX DY DZ\n"
+"M G WGS 84 121 +0.000000e+00 +0.000000e+00 +0.000000e+00 +0.000000e+00 +0.000000e+00\n"
+"\n"
+"H COORDINATE SYSTEM\n"
+"U LAT LON DM\n"
+"\n"
+"H IDNT LATITUDE LONGITUDE DATE TIME ALT DESCRIPTION PROXIMITY SYMBOL ;waypts\n");
+
+ waypt_disp_all(gpsutil_disp);
+}
+
+
+ff_vecs_t pcx_vecs = {
+ rd_init,
+ wr_init,
+ rd_deinit,
+ wr_deinit,
+ data_read,
+ data_write,
+};
--- /dev/null
+/*
+ Generic queue utilities.
+
+ Copyright (C) 2002 Robert Lipe, robertlipe@usa.net
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
+
+ */
+
+#include "queue.h"
+
+void
+enqueue(queue *new, queue *old)
+{
+ new->next = old->next;
+ new->prev = old;
+ old->next->prev = new;
+ old->next = new;
+}
+
+queue *
+dequeue(queue *element)
+{
+ queue *prev = element->prev;
+ queue *next = element->next;
+
+ next->prev = prev;
+ prev->next = next;
+ return element;
+}
--- /dev/null
+/*
+ Generic queueing utilities.
+
+ Copyright (C) 2002 Robert Lipe, robertlipe@usa.net
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
+
+ */
+
+typedef struct queue {
+ struct queue *next;
+ struct queue *prev;
+} queue;
+
+void enqueue(queue *new, queue *old);
+queue * dequeue(queue *element);
+
+#define QUEUE_INIT(head) (head)->next = (head)->prev = head
+#define QUEUE_FIRST(head) (head)->next
+#define QUEUE_NEXT(element) (element)->next
+#define QUEUE_LAST(head) (head)->prev
+#define QUEUE_EMPTY (head)->next = head
+
+#define ENQUEUE_TAIL(listhead, element) \
+ enqueue(element, (listhead)->prev)
+
+#define QUEUE_FOR_EACH(listhead, element, tmp) \
+ for ((element) = QUEUE_FIRST(listhead); \
+ (tmp) = QUEUE_NEXT(element), \
+ (element) != (listhead); \
+ (element) = (tmp))
--- /dev/null
+<?xml version="1.0"?><loc version="1.0" src="EasyGPS">
+<waypoint>
+<name id="GCEBB"><![CDATA[Mountain Bike Heaven by susy1313]]></name>
+<coord lat="35.972033" lon="-87.134700"></coord>
+<link text ="Cache Details">http://www.geocaching.com/seek/cache_details.asp?ID=3771</link>
+</waypoint>
+<waypoint>
+<name id="GC1A37"><![CDATA[The Troll by a182pilot & Family]]></name>
+<coord lat="36.090683" lon="-86.679550"></coord>
+<link text ="Cache Details">http://www.geocaching.com/seek/cache_details.asp?ID=6711</link>
+</waypoint>
+<waypoint>
+<name id="GC1C2B"><![CDATA[Dive Bomber by JoGPS & family]]></name>
+<coord lat="35.996267" lon="-86.620117"></coord>
+<link text ="Cache Details">http://www.geocaching.com/seek/cache_details.asp?ID=7211</link>
+</waypoint>
+<waypoint>
+<name id="GC25A9"><![CDATA[FOSTER by JoGPS & Family]]></name>
+<coord lat="36.038483" lon="-86.648617"></coord>
+<link text ="Cache Details">D=9641</link>
+</waypoint>
+<waypoint>
+<name id="GC2723"><![CDATA[Logan Lighthouse by JoGps & Family]]></name>
+<coord lat="36.112183" lon="-86.741767"></coord>
+<link text ="Cache Details">http://www.geocaching.com/seek/cache_details.asp?ID=10019</link>
+</waypoint>
+<waypoint>
+<name id="GC2B71"><![CDATA[Ganier Cache by Susy1313]]></name>
+<coord lat="36.064083" lon="-86.790517"></coord>
+<link text ="Cache Details">http://www.geocaching.com/seek/cache_details.asp?ID=11121</link>
+</waypoint>
+<waypoint>
+<name id="GC309F"><![CDATA[Shy's Hill by FireFighterEng33]]></name>
+<coord lat="36.087767" lon="-86.809733"></coord>
+<link text ="Cache Details">http://www.geocaching.com/seek/cache_details.asp?ID=12447</link>
+</waypoint>
+<waypoint>
+<name id="GC317A"><![CDATA[GittyUp by JoGPS / Warner Parks]]></name>
+<coord lat="36.057500" lon="-86.892000"></coord>
+<link text ="Cache Details">http://www.geocaching.com/seek/cache_details.asp?ID=12666</link>
+</waypoint>
+<waypoint>
+<name id="GC317D"><![CDATA[Inlighting by JoGPS / Warner Parks]]></name>
+<coord lat="36.082800" lon="-86.867283"></coord>
+<link text ="Cache Details">http://www.geocaching.com/seek/cache_details.asp?ID=12669</link>
+</waypoint>
+</loc>
--- /dev/null
+GCEBB 3597.203N 08713.470W 0000000m Mountain Bike Heaven by susy13 a
+GC1A37 3609.068N 08667.955W 0000000m The Troll by a182pilot & Famil a
+GC1C2B 3599.627N 08662.012W 0000000m Dive Bomber by JoGPS & family a
+GC25A9 3603.848N 08664.862W 0000000m FOSTER by JoGPS & Family a
+GC2723 3611.218N 08674.177W 0000000m Logan Lighthouse by JoGps & Fa a
+GC2B71 3606.408N 08679.052W 0000000m Ganier Cache by Susy1313 a
+GC309F 3608.777N 08680.973W 0000000m Shy's Hill by FireFighterEng33 a
+GC317A 3605.750N 08689.200W 0000000m GittyUp by JoGPS / Warner Park a
+GC317D 3608.280N 08686.728W 0000000m Inlighting by JoGPS / Warner P a
--- /dev/null
+/*
+ Copyright (C) 2002 Robert Lipe, robertlipe@usa.net
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
+
+ */
+
+#include <stdio.h>
+#include "defs.h"
+
+static queue route_head;
+
+void
+route_init(void)
+{
+ QUEUE_INIT(&route_head);
+}
+
+void
+route_add(waypoint *wpt)
+{
+ ENQUEUE_TAIL(&route_head, &wpt->Q);
+}
+
+void
+route_disp_all(waypt_cb cb)
+{
+ queue *elem, *tmp;
+ waypoint *waypointp;
+
+ QUEUE_FOR_EACH(&route_head, elem, tmp) {
+ waypointp = (waypoint *) elem;
+ (*cb)(waypointp);
+ }
+}
--- /dev/null
+PNAME=./gpsbabel
+
+# Geocaching .loc
+${PNAME} -i geo -f geocaching.loc -o geo -F /tmp/gl.loc
+diff /tmp/gl.loc reference
+
+# GPSUtil
+${PNAME} -i geo -f geocaching.loc -o gpsutil -F /tmp/gu.wpt
+diff /tmp/gu.wpt reference
+
+# GPSman
+${PNAME} -i geo -f geocaching.loc -o gpsman -F /tmp/gm.gm
+${PNAME} -i gpsman -f /tmp/gm.gm -o gpsutil -F /tmp/gm.gm+
+diff /tmp/gm.gm+ /tmp/gu.wpt
+
+# GPX
+${PNAME} -i geo -f geocaching.loc -o gpx -F /tmp/gl.gpx
+${PNAME} -i gpx -f /tmp/gl.gpx -o gpsutil -F /tmp/gpx.gpx
+diff /tmp/gpx.gpx /tmp/gu.wpt
+
+# Magellan Mapsend
+${PNAME} -i geo -f geocaching.loc -o mapsend -F /tmp/mm.mapsend
+${PNAME} -i mapsend -f /tmp/mm.mapsend -o gpsutil -F /tmp/mm.gps
+diff /tmp/mm.gps /tmp/gu.wpt
+
+# Garmin Mapsource
+#${PNAME} -i geo -f geocaching.loc -o mapsource -F /tmp/mm.mapsource
+#${PNAME} -i mapsource -f /tmp/mm.mapsource -o gpsutil -F /tmp/ms.gps
+# diff /tmp/ms.gps /tmp/gu.wpt
+
+# Magellan serial
+# TODO
+
+
+# CSV (Comma separated value) data.
+
+#${PNAME} -i geo -f geocaching.loc -o csv -F /tmp/csv.csv
+#${PNAME} -i csv -f /tmp/csv.csv -o gpsutil -F /tmp/csv2.csv
+#diff /tmp/csv2.csv /tmp/gu.wpt
+
+# PCX (Garmin mapsource import) file format
+${PNAME} -i geo -f geocaching.loc -o pcx -F /tmp/mm.pcx
+${PNAME} -i pcx -f /tmp/mm.pcx -o gpsutil -F /tmp/pcx.gps
+diff /tmp/mm.gps /tmp/gu.wpt
+
--- /dev/null
+/*
+ Access to U.S. Census Bureau "tiger" format.
+
+ Copyright (C) 2002 Robert Lipe, robertlipe@usa.net
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
+
+ */
+
+#include "defs.h"
+#include "magellan.h"
+
+static FILE *file_in;
+static FILE *file_out;
+
+static void
+rd_init(const char *fname)
+{
+ file_in = fopen(fname, "r");
+ if (file_in == NULL) {
+ fatal("GPSUTIL: Cannot open %s for reading\n", fname);
+ }
+}
+
+static void
+rd_deinit(void)
+{
+ fclose(file_in);
+}
+
+static void
+wr_init(const char *fname)
+{
+ file_out = fopen(fname, "w");
+ if (file_out == NULL) {
+ fatal("GPSUTIL: Cannot open %s for writing\n", fname);
+ }
+}
+
+static void
+wr_deinit(void)
+{
+ fclose(file_out);
+}
+
+static void
+data_read(void)
+{
+abort();
+#if 0
+ char name[9], desc[30];
+ double lat,lon;
+ char latdir, londir;
+ long alt;
+ char alttype;
+ char icon[3] = {0};
+ waypoint *wpt_tmp;
+
+ while( fscanf(file_in, "%s %le%c %le%c %ld%c %30[^,] %c",
+ name, &lat, &latdir, &lon, &londir,
+ &alt, &alttype, desc, icon) > 0) {
+ wpt_tmp = calloc(sizeof(*wpt_tmp),1);
+ if (wpt_tmp == NULL) {
+ fatal("GPSMAN: cannot allocate memory\n");
+ }
+ wpt_tmp->position.altitude.altitude_meters = alt;
+ wpt_tmp->shortname = strdup(name);
+ wpt_tmp->description = strdup(desc);
+ wpt_tmp->creation_time = time(NULL);
+
+ if (latdir == 'S') lat = -lat;
+ if (londir == 'W') lon = -lon;
+ wpt_tmp->position.longitude.degrees = lon/100.0;
+ wpt_tmp->position.latitude.degrees = lat/100.0;
+ wpt_tmp->icon_descr = strdup(icon);
+
+ waypt_add(wpt_tmp);
+ }
+#endif
+}
+
+static void
+gpsutil_disp(waypoint *wpt)
+{
+ fprintf(file_out, "%f,%f:redpin:%s\n",
+ wpt->position.longitude.degrees,
+ wpt->position.latitude.degrees,
+ wpt->description);
+}
+
+static void
+data_write(void)
+{
+ waypt_disp_all(gpsutil_disp);
+}
+
+
+ff_vecs_t tiger_vecs = {
+ rd_init,
+ wr_init,
+ rd_deinit,
+ wr_deinit,
+ data_read,
+ data_write,
+};
--- /dev/null
+/*
+ Misc utilities.
+
+ Copyright (C) 2002 Robert Lipe, robertlipe@usa.net
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
+
+ */
+
+#include "defs.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+coord
+mkposn(const char *string)
+{
+ coord coord = {0};
+ sscanf(string, "%lf", &coord.degrees);
+ return coord;
+}
+
+void
+printposn(coord *c, int is_lat)
+{
+ char d;
+ if (is_lat) {
+ if (c->degrees < 0) d = 'S'; else d = 'N';
+ } else {
+ if (c->degrees < 0) d = 'W'; else d = 'E';
+ }
+ printf("%lf%c ", fabs(c->degrees), d);
+}
+
+void
+fprintdms(FILE *file, coord *c, int is_lat)
+{
+ char d;
+ if (is_lat) {
+ if (c->degrees < 0) d = 'S'; else d = 'N';
+ } else {
+ if (c->degrees < 0) d = 'W'; else d = 'E';
+ }
+ fprintf(file, "%c%lf\t", d, fabs(c->degrees));
+}
+void
+fatal(const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ exit(1);
+}
--- /dev/null
+/*
+ Describe vectors containing file operations.
+
+ Copyright (C) 2002 Robert Lipe, robertlipe@usa.net
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
+
+ */
+
+#include <stdio.h>
+#include "defs.h"
+
+typedef struct {
+ ff_vecs_t *vec;
+ char *name;
+ char *desc;
+} vecs_t;
+
+extern ff_vecs_t geo_vecs;
+extern ff_vecs_t gpsman_vecs;
+extern ff_vecs_t gpx_vecs;
+extern ff_vecs_t mag_vecs;
+extern ff_vecs_t mapsend_vecs;
+extern ff_vecs_t mapsource_vecs;
+extern ff_vecs_t gpsutil_vecs;
+extern ff_vecs_t tiger_vecs;
+extern ff_vecs_t pcx_vecs;
+extern ff_vecs_t csv_vecs;
+
+static
+vecs_t vec_list[] = {
+ {
+ &geo_vecs,
+ "geo",
+ "Geocaching.com .loc"
+ },
+ {
+ &gpsman_vecs,
+ "gpsman",
+ "GPSman"
+ },
+ {
+ &gpx_vecs,
+ "gpx",
+ "GPX XML"
+ },
+ {
+ &mag_vecs,
+ "magellan",
+ "Magellan protocol"
+ },
+ {
+ &mapsend_vecs,
+ "mapsend",
+ "Magellan Mapsend"
+ },
+ {
+ &pcx_vecs,
+ "pcx",
+ "Garmin PCX5"
+ },
+ {
+ &mapsource_vecs,
+ "mapsource",
+ "Garmin Mapsource"
+ },
+ {
+ &gpsutil_vecs,
+ "gpsutil",
+ "gpsutil"
+ },
+ {
+ &tiger_vecs,
+ "tiger",
+ "U.S. Census Bureau Tiger Mapping Service"
+ },
+ {
+ &csv_vecs,
+ "csv",
+ "Comma separated values"
+ },
+ {
+ NULL,
+ NULL,
+ NULL
+ }
+};
+
+ff_vecs_t *
+find_vec(char *const vecname)
+{
+ vecs_t *vec = vec_list;
+ while (vec->vec) {
+ if (strcmp(vecname, vec->name) == 0) {
+ return vec->vec;
+ }
+ vec++;
+ }
+ return NULL;
+}
+
+void
+disp_vecs(void)
+{
+ vecs_t *vec;
+ for (vec = vec_list; vec->vec; vec++) {
+ printf("%-20.20s %-50.50s\n",
+ vec->name, vec->desc);
+ }
+}
--- /dev/null
+/*
+ Perform various operations on waypoints.
+
+ Copyright (C) 2002 Robert Lipe, robertlipe@usa.net
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
+
+ */
+
+#include <stdio.h>
+#include "defs.h"
+
+static queue waypt_head;
+static unsigned int waypt_ct;
+
+void
+waypt_init(void)
+{
+ QUEUE_INIT(&waypt_head);
+}
+
+void
+waypt_add(waypoint *wpt)
+{
+ ENQUEUE_TAIL(&waypt_head, &wpt->Q);
+ waypt_ct++;
+}
+
+unsigned int
+waypt_count(void)
+{
+ return waypt_ct;
+}
+
+void
+waypt_disp(waypoint *wpt)
+{
+ if (wpt->creation_time) {
+ printf("%s ", ctime(&wpt->creation_time));
+ }
+ printposn(&wpt->position.latitude,1);
+ printposn(&wpt->position.longitude,0);
+ printf("%s/%s %f\n",
+ wpt->shortname,
+ wpt->description,
+ wpt->position.altitude.altitude_meters);
+}
+
+void
+waypt_disp_all(waypt_cb cb)
+{
+ queue *elem, *tmp;
+ waypoint *waypointp;
+
+ QUEUE_FOR_EACH(&waypt_head, elem, tmp) {
+ waypointp = (waypoint *) elem;
+ (*cb) (waypointp);
+ }
+}